/*
 -- IOTA Crypto Core
 --
 -- 2018 by Thomas Pototschnig <microengineer18@gmail.com>
 -- discord: pmaxuw#8292
 -- https://gitlab.com/iccfpga-rv
 --
 -- Permission is hereby granted, free of charge, to any person obtaining
 -- a copy of this software and associated documentation files (the
 -- "Software"), to deal in the Software without restriction, including
 -- without limitation the rights to use, copy, modify, merge, publish,
 -- distribute, sublicense, and/or sell copies of the Software, and to
 -- permit persons to whom the Software is furnished to do so, subject to
 -- the following conditions:
 --
 -- The above copyright notice and this permission notice shall be
 -- included in all copies or substantial portions of the Software.
 --
 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 -- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 -- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 -- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 -- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWAR
 */

#include "main.h"
#include "xparameters.h"        // Project memory and device map
#include "xgpio.h"              // Xilinx GPIO routines
#include "gpio/secure_gpio.h"

XGpio MMDATA Gpio_IIC; /* The driver instance for the IIC GPIO */

extern "C" void MMTEXT gpio_i2c_data_high() {
	SecureGPIO::setBit(SecureGPIO::sda_t);
}

extern "C" void MMTEXT gpio_i2c_data_low() {
	SecureGPIO::clrBit(SecureGPIO::sda_t);
}

extern "C" void MMTEXT gpio_i2c_clock_high() {
	SecureGPIO::setBit(SecureGPIO::scl_t);
}

extern "C" void MMTEXT gpio_i2c_clock_low() {
	SecureGPIO::clrBit(SecureGPIO::scl_t);
}

extern "C" int MMTEXT gpio_i2c_data_in() {
	return SecureGPIO::readBit(SecureGPIO::sda_i);
}

namespace SecureGPIO {
	uint32_t shadow;
	// extern "C" because it is used by a c-class in microchips crypto-library
	int MMTEXT gpio_init() {
		// Define local variables
		int status;

		/*
		 * Initialize the GPIO driver so that it's ready to use,
		 * specify the device ID that is generated in xparameters.h
		 */
		status = XGpio_Initialize(&Gpio_IIC, XPAR_AXI_GPIO_1_DEVICE_ID);
		if (status != XST_SUCCESS) {
			return XST_FAILURE;
		}

	// not needed ... fixed in axi-core
	//	XGpio_SetDataDirection(&Gpio_IIC, 1, 0xFFFFFFF0);
	//	XGpio_SetDataDirection(&Gpio_IIC, 2, 0xFFFFFFFF);

		XGpio_DiscreteWrite(&Gpio_IIC, 1, 0x0a);
		shadow = 0x0000000a;

		volatile uint32_t tmp = XGpio_DiscreteRead(&Gpio_IIC, 2);
		return XST_SUCCESS;
	}


	void MMTEXT setBit(BitsOut bit) {
		shadow |= bit;
		XGpio_DiscreteWrite(&Gpio_IIC, 1, shadow);   // Set LEDs
	}

	void MMTEXT clrBit(BitsOut bit) {
		shadow &= ~bit;
		XGpio_DiscreteWrite(&Gpio_IIC, 1, shadow);   // Set LEDs
	}

	int MMTEXT readBit(BitsIn bit) {
		return !!(XGpio_DiscreteRead(&Gpio_IIC, 2) & bit);
	}

	// trigger FPGA reconfiguration
	void MMTEXT triggerIPROG(uint32_t wbstar) {
		shadow &= ~(0xffff0000);
		shadow |= (wbstar & 0xffff0000);
		shadow |= iprog;
		XGpio_DiscreteWrite(&Gpio_IIC, 1, shadow);
	}

}
